package com.speeda.pda.weight.huamao;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.ScrollView;
import android.widget.Toast;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Set;
import java.util.UUID;

/**
 * Created by Administrator on 2015/12/23.
 */
public class HuamaoPlugin extends CordovaPlugin {

    public static String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB";
    private InputStream mmInStream;
    private OutputStream mmOutStream;

    private ArrayList<Integer> nNeeds; 
    private ArrayList<String> sRecvs; 
    private int nCurrent;

    BluetoothAdapter btAdapt = null;
    BluetoothSocket btSocket = null;

    Boolean bConnect = false;
    String strName = null;
    String strAddress = null;

    private double weightData = 0.00;


    /**
     * 
     */
    CallbackContext callbackContextForRecData;

    /**
     *
     */
    public final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case Common.MESSAGE_CONNECT:
                    new Thread(new Runnable() {
                        public void run() {
                            InputStream tmpIn;
                            OutputStream tmpOut;
                            try {

                                UUID uuid = UUID.fromString(SPP_UUID);
                                BluetoothDevice btDev = btAdapt
                                        .getRemoteDevice(strAddress);
                                btSocket = btDev.createInsecureRfcommSocketToServiceRecord(uuid);
                                //.createRfcommSocketToServiceRecord(uuid);
                                btSocket.connect();
                                tmpIn = btSocket.getInputStream();
                                tmpOut = btSocket.getOutputStream();
                            } catch (Exception e) {
                                Log.d(Common.TAG, "Error connected to: "
                                        + strAddress);
                                bConnect = false;
                                mmInStream = null;
                                mmOutStream = null;
                                btSocket = null;
                                e.printStackTrace();
                                mHandler.sendEmptyMessage(Common.MESSAGE_CONNECT_LOST);
                                return;
                            }
                            mmInStream = tmpIn;
                            mmOutStream = tmpOut;
                            mHandler.sendEmptyMessage(Common.MESSAGE_CONNECT_SUCCEED);
                        }

                    }).start();
                    break;
                case Common.MESSAGE_CONNECT_SUCCEED:
                    
                    bConnect = true;
                    new Thread(new Runnable() {
                        public void run() {
                            byte[] bufRecv = new byte[1024];
                            int nRecv = 0;
                            while (bConnect) {
                                try {
                                    nRecv = mmInStream.read(bufRecv);
                                    if (nRecv < 1) {
                                        Thread.sleep(100);
                                        continue;
                                    }

                                    byte[] nPacket = new byte[nRecv];
                                    System.arraycopy(bufRecv, 0, nPacket, 0, nRecv);
                                    mHandler.obtainMessage(Common.MESSAGE_RECV,
                                            nRecv, -1, nPacket).sendToTarget();
                                    Thread.sleep(100);
                                } catch (Exception e) {
                                    Log.e(Common.TAG, "Recv thread:" + e.getMessage());
                                    mHandler.sendEmptyMessage(Common.MESSAGE_EXCEPTION_RECV);
                                    break;
                                }
                            }
                            Log.e(Common.TAG, "Exit while");
                        }
                    }).start();
                    break;
                case Common.MESSAGE_EXCEPTION_RECV:
                case Common.MESSAGE_CONNECT_LOST:
                    
                    try {
                        if (mmInStream != null)
                            mmInStream.close();
                        if (mmOutStream != null)
                            mmOutStream.close();
                        if (btSocket != null)
                            btSocket.close();
                    } catch (IOException e) {
                        Log.e(Common.TAG, "Close Error");
                        e.printStackTrace();
                    } finally {
                        mmInStream = null;
                        mmOutStream = null;
                        btSocket = null;
                        bConnect = false;
                    }
                    break;
                case Common.MESSAGE_WRITE:

                    break;
                case Common.MESSAGE_READ:

                    break;
                case Common.MESSAGE_RECV:

                    byte[] bBuf = (byte[]) msg.obj;
                   

                    String data = bytesToString(bBuf, msg.arg1);
                    String[] splitDatas = data.split("=");
                    for(String splitData : splitDatas){

                        if(splitData.trim().equals(""))
                            continue;

                        data = new StringBuilder(splitData).reverse().toString();
                        break;
                    }

                    // 
                    try {
                        Double w = Double.parseDouble(data);

                        if (w > 0) {

                            weightData = w;
                            if (callbackContextForRecData != null) {
                                PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, String.format("%.2f", w));
                                pluginResult.setKeepCallback(true);
                                callbackContextForRecData.sendPluginResult(pluginResult);
                            }
                        }
                    }catch(Exception ex){
                        //
                    }

                    break;
                case Common.MESSAGE_TOAST:

                    break;
            }
        }
    };

    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {

        if("enable".equals(action)){
            this.initDevice(args,callbackContext);
        }

        if("getDevices".equals(action)) {
            this.getBoundDevices(args,callbackContext);
        }

        if("recvData".equals(action)) {
            this.receiveData(args,callbackContext);
        }

        if("getWeight".equals(action)) {
            this.getWeightData(args,callbackContext);
        }

        return true;
    }

    /**
     * 
     * @param args
     * @param callbackContext
     */
    private void initDevice(JSONArray args, CallbackContext callbackContext){
        btAdapt = BluetoothAdapter.getDefaultAdapter();

        if(btAdapt == null){
            // 
            return;
        }

        //
        if (!btAdapt.isEnabled()) {
            // 
            //Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            //cordova.startActivityForResult(this, intent, REQUEST_BT_ENABLE);

            btAdapt.enable();
        }
    }

    /**
     * 
     * @param args
     * @param callbackContext
     */
    private void getBoundDevices(JSONArray args, CallbackContext callbackContext){
        Set<BluetoothDevice> pairedDevices = btAdapt.getBondedDevices();
        StringBuilder devices = new StringBuilder();
        if (pairedDevices.size() > 0) {
            for (BluetoothDevice device : pairedDevices) {
                String str = device.getName() + "|" + device.getAddress();
                if(devices.length() > 0)
                    devices.append("\n");
                devices.append(str);
            }
        }

        PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, devices.toString());
        pluginResult.setKeepCallback(true);
        callbackContext.sendPluginResult(pluginResult);
    }

    /**
     * 
     * @param args
     * @param callbackContext
     */
    private void receiveData(JSONArray args, CallbackContext callbackContext){

        if(this.callbackContextForRecData != null) 
            return;

        this.callbackContextForRecData = callbackContext;

        JSONObject obj = this.getArgsObject(args);
        this.strAddress = this.getAddress(obj);
        this.mHandler.sendEmptyMessageDelayed(Common.MESSAGE_CONNECT, 1000);
    }

    private void getWeightData(JSONArray args,CallbackContext callbackContext){

        PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, String.format("%.2f", weightData));
        pluginResult.setKeepCallback(true);
        callbackContextForRecData.sendPluginResult(pluginResult);

    }

    // 

    /**
     * 
     * @param args
     * @return
     */
    private JSONObject getArgsObject(JSONArray args) {
        if (args.length() == 1) {
            try {
                return args.getJSONObject(0);
            } catch (JSONException ex) {
            }
        }

        return null;
    }

    /**
     * 
     * @param obj
     * @return
     */
    private String getAddress(JSONObject obj) {
        // Get the address string from arguments
        String address = obj.optString("address", null);

        if (address == null) {
            return null;
        }

        // Validate address format
        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
            return null;
        }

        return address;
    }

    /**
     * 
     * @param b
     * @param length
     * @return
     */
    public static String bytesToString(byte[] b, int length) {
        StringBuffer result = new StringBuffer("");
        for (int i = 0; i < length; i++) {
            result.append((char) (b[i]));
        }

        return result.toString();
    }

    public class Common {
        public static final int MESSAGE_STATE_CHANGE = 1;
        public static final int MESSAGE_READ = 2;
        public static final int MESSAGE_WRITE = 3;
        public static final int MESSAGE_DEVICE_NAME = 4;
        public static final int MESSAGE_TOAST = 5;

        public static final int MESSAGE_CONNECT = 6;
        public static final int MESSAGE_CONNECT_SUCCEED = 7;
        public static final int MESSAGE_CONNECT_LOST = 8;
        public static final int MESSAGE_RECV = 10;
        public static final int MESSAGE_EXCEPTION_RECV = 11;
        public static final String TOAST = "toast";
        public static final String TAG = "BlueToothTool";

    }

}